home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / iphdr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  3.6 KB  |  168 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "ip.h"
  4. #include "internet.h"
  5.  
  6. /* Convert IP header in host format to network mbuf
  7.  * If cflag != 0, take checksum from structure,
  8.  * otherwise compute it automatically.
  9.  */
  10. struct mbuf *htonip(ip,data,cflag)
  11. struct ip *ip;
  12. struct mbuf *data;
  13. int cflag;
  14. {
  15.     int16 hdr_len;
  16.     struct mbuf *bp;
  17.     register char *cp;
  18.     int16 checksum;
  19.     int16 fl_offs;
  20.  
  21.     hdr_len = IPLEN + ip->optlen;
  22.     if((bp = pushdown(data,hdr_len)) == NULLBUF){
  23.         free_p(data);
  24.         return NULLBUF;
  25.     }
  26.     cp = bp->data;
  27.     
  28.     *cp++ = (IPVERSION << 4) | (hdr_len >> 2);
  29.     *cp++ = ip->tos;
  30.     cp = put16(cp,ip->length);
  31.     cp = put16(cp,ip->id);
  32.     fl_offs = ip->offset >> 3;
  33.     if(ip->flags.df)
  34.         fl_offs |= 0x4000;
  35.     if(ip->flags.mf)
  36.         fl_offs |= 0x2000;
  37.  
  38.     cp = put16(cp,fl_offs);
  39.     *cp++ = ip->ttl;
  40.     *cp++ = ip->protocol;
  41.     cp = put16(cp,0);    /* Clear checksum */
  42.     cp = put32(cp,ip->source);
  43.     cp = put32(cp,ip->dest);
  44.     if(ip->optlen != 0)
  45.         memcpy(cp,ip->options,ip->optlen);
  46.  
  47.     /* Compute checksum and insert into header */
  48.     if(cflag)
  49.         checksum = ip->checksum;
  50.     else {
  51.         checksum = cksum(NULLHEADER,bp,hdr_len);
  52.     }
  53.     put16(&bp->data[10],checksum);
  54.     return bp;
  55. }
  56.  
  57. /* Extract an IP header from mbuf */
  58. int ntohip(ip,bpp)
  59. struct ip *ip;
  60. struct mbuf **bpp;
  61. {
  62.     int16 ihl;
  63.     int16 fl_offs;
  64.     char ipbuf[IPLEN];
  65.  
  66.     if(pullup(bpp,ipbuf,IPLEN) != IPLEN)
  67.         return -1;
  68.  
  69.     ip->version = (ipbuf[0] >> 4) & 0xf;
  70.     ip->tos = ipbuf[1];
  71.     ip->length = get16(&ipbuf[2]);
  72.     ip->id = get16(&ipbuf[4]);
  73.     fl_offs = get16(&ipbuf[6]);
  74.     ip->offset = (fl_offs & 0x1fff) << 3;
  75.     ip->flags.mf = (fl_offs & 0x2000) ? 1 : 0;
  76.     ip->flags.df = (fl_offs & 0x4000) ? 1 : 0;
  77.     ip->ttl = ipbuf[8];
  78.     ip->protocol = ipbuf[9];
  79.     ip->checksum = get16(&ipbuf[10]);
  80.     ip->source = get32(&ipbuf[12]);
  81.     ip->dest = get32(&ipbuf[16]);
  82.  
  83.     ihl = (ipbuf[0] & 0xf) << 2;
  84.     if(ihl < IPLEN){
  85.         /* Bogus packet; header is too short */
  86.         return -1;
  87.     }
  88.     ip->optlen = ihl - IPLEN;
  89.     if(ip->optlen != 0)
  90.         pullup(bpp,ip->options,ip->optlen);
  91.  
  92.     return ip->optlen + IPLEN;
  93. }
  94.  
  95. /* Perform end-around-carry adjustment */
  96. int16 eac(sum)
  97. register int32 sum;    /* Carries in high order 16 bits */
  98. {
  99.     register int16 csum;
  100.  
  101.     while((csum = sum >> 16) != 0)
  102.         sum = csum + (sum & 0xffffL);
  103.     return (int16) (sum & 0xffffl);    /* Chops to 16 bits */
  104. }
  105.  
  106. /* Checksum a mbuf chain, with optional pseudo-header */
  107. int16 cksum(ph,m,len)
  108. struct pseudo_header *ph;
  109. register struct mbuf *m;
  110. int16 len;
  111. {
  112.     register int16 cnt, total;
  113.     register int32 sum, csum;
  114.     register char *up;
  115.     int16 csum1;
  116.     int swap = 0;
  117.  
  118.     sum = 0l;
  119.  
  120.     /* Sum pseudo-header, if present */
  121.     if(ph != NULLHEADER){
  122.         sum = hiword(ph->source);
  123.         sum += loword(ph->source);
  124.         sum += hiword(ph->dest);
  125.         sum += loword(ph->dest);
  126.         sum += uchar(ph->protocol);
  127.         sum += ph->length;
  128.     }
  129.     /* Now do each mbuf on the chain */
  130.     for(total = 0; m != NULLBUF && total < len; m = m->next) {
  131.         cnt = min(m->cnt, len - total);
  132.         up = (char *)m->data;
  133.         csum = 0;
  134.  
  135.         if(((long)up) & 1){
  136.             /* Handle odd leading byte */
  137.             if(swap)
  138.                 csum = uchar(*up++);
  139.             else
  140.                 csum = (int16)(uchar(*up++) << 8);
  141.             cnt--;
  142.             swap = !swap;
  143.         }
  144.         if(cnt > 1){
  145.             /* Have the primitive checksumming routine do most of
  146.              * the work. At this point, up is guaranteed to be on
  147.              * a short boundary
  148.              */
  149.             csum1 = lcsum((unsigned short *)up, (int16)(cnt >> 1));
  150.             if(swap)
  151.                 csum1 = (csum1 << 8) | (csum1 >> 8);
  152.             csum += csum1;
  153.         }
  154.         /* Handle odd trailing byte */
  155.         if(cnt & 1){
  156.             if(swap)
  157.                 csum += uchar(up[--cnt]);
  158.             else
  159.                 csum += (int16)(uchar(up[--cnt]) << 8);
  160.             swap = !swap;
  161.         }
  162.         sum += csum;
  163.         total += m->cnt;
  164.     }
  165.     /* Do final end-around carry, complement and return */
  166.     return (int16)(~eac(sum) & 0xffff);
  167. }
  168.